package com.progenies.ecg.model.codeparts.lines;

import com.progenies.ecg.model.ValueReference;
import com.progenies.ecg.model.codeparts.ICodePart;

public interface IVariableFactory
{
	
	/**
	 * Generate a LineCodePart that creates a local variable, without value assignment.
	 * @param name Name of the local variable
	 * @param type Class type of the variable.
	 * @return LineCodePart created
	 */
	public <T> LineCodePart createLocalVariable(String name, Class<T> type);
	
	
	/**
	 * Generate a LineCodePart that creates a local variable, without value assignment, but initialize it if specified
	 * @param name Name of the local variable
	 * @param type Class type of the variable.
	 * @param initialize Marks if the variable must be initialized. It only works on non-primitive variable types, and only if the type has a default constructor. In other case, use createObjectAndStore method.  
	 * @return LineCodePart created
	 */
	public <T> LineCodePart createLocalVariableAndInitialize(String name, Class<T> type);
	

	public <T> LineCodePart createLocalArrayVariable(String name, Class<T> type, ValueReference<?>[] variableReferences);
	
	public <T> LineCodePart createLocalArrayVariable(String name, Class<T> type, ValueReference<?>[][] variableReferences);
	
	/**
	 * Generate a LineCodePart that creates a local variable, without value assignment, but initialize it if specified
	 * @param name Name of the local variable
	 * @param type Class type of the variable.
	 * @param initialize Marks if the variable must be initialized. It only works on non-primitive variable types, and only if the type has a default constructor. In other case, use createObjectAndStore method.  
	 * @return LineCodePart created
	 */
	public <T> LineCodePart createLocalArrayVariable(String name, Class<T> type, int arraySize);
	
	public <T> LineCodePart createLocalArrayVariable(String name, Class<T> type, int matrixSize[]);

	/**
	 * Generate a LineCodePart that creates a local variable, assigning an initial static value. An static value is defined at compile time, not at runtime. 
	 * @param name Name of the local variable
	 * @param type Class type of the variable.
	 * @param value Static value to assign.  
	 * @return LineCodePart created
	 */
	public <T> LineCodePart createLocalVariable(String name, Class<T> type,	T value);
	
	public <T> LineCodePart createLocalVariableFromVariable(String name, Class<T> type, String referencedVariablename);
	
	
	
	
	public <T> LineCodePart createEmptyArrayAndStore(Class<T> type, int arrayDimensions[], String name);
	
	
	public <T> LineCodePart createArrayAndStore(Class<T> type, T value, String name);
	
	public <T> LineCodePart createArrayAndStore(Class<T> type, String name, ValueReference<?>[] variableReferences);

	public <T> LineCodePart createArrayAndStore(Class<T> type, String name, ValueReference<?>[][] variableReferences);

	


	/**
	 * Generate a LineCodePart able to change a variable value. The scope of the variable is automatically obtained from its name.
	 * @param name name of the variable
	 * @param value value to assign to the variable.
	 * @return LineCodePart created
	 */
	public <T> LineCodePart setVariableValue(String name, T value);
	
	/**
	 * Generate a LineCodePart able to change a variable value from the value of other variable.
	 * The scope of both variables is automatically obtained from their name.
	 * @param name name of the variable
	 * @param originName name of the origin variable that hold the value to assign to the variable.
	 * @return LineCodePart created
	 */
	public ICodePart setVariableValueFromVariable(String name, String originName);
	
	/**
	 * Generate a LineCodePart able to change a variable value from the value of other variable.
	 * The scope of both variables is automatically obtained from their name.
	 * @param name name of the variable
	 * @param objectVariableName name of the origin variable that hold the object that owns the field with the value to assign to the variable.
	 * @param fieldName name of the variable inside object that holds the value
	 * @return LineCodePart created
	 */
	public ICodePart setVariableValueFromObjectField(String name, String objectVariableName, String fieldName, Class<?> fieldType);
	
	
	/**
	 * Generate a LineCodePart able to change a variable value from the value of other variable.
	 * The scope of both variables is automatically obtained from their name.
	 * @param name name of the variable
	 * @param ownerClass Class that holds the static field with the value to assign to the variable.
	 * @param staticFieldName name of the static field inside ownerClass that holds the value
	 * @return LineCodePart created
	 */
	public ICodePart setVariableValueFromStaticClassField(String name, Class<?> ownerClass, String staticFieldName , Class<?> fieldType);


	public ICodePart setVariableValueNull(String variableName);


	
	public LineCodePart incrementVariable(String name);
	
	public LineCodePart incrementVariable(String name, int ammount);

	public LineCodePart decrementVariable(String name);


	public <T> LineCodePart setStaticFieldValue(String name, Class<?> ownerClass, T value);

	public <T> LineCodePart setFieldInFieldValue(String name, String fieldOwner, T value);





}
